package edu.pitt.dbmi.odie.gapp.gwt.client.util.picker.tui;

import java.util.ArrayList;

import com.smartgwt.client.core.Rectangle;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Dialog;
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.form.fields.events.IconClickEvent;
import com.smartgwt.client.widgets.form.fields.events.IconClickHandler;
import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
import com.smartgwt.client.widgets.form.fields.events.KeyPressHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.LayoutSpacer;
import com.smartgwt.client.widgets.layout.VStack;

import edu.pitt.dbmi.odie.gapp.gwt.client.util.ODIE_ClientUtils;
import edu.pitt.dbmi.odie.gapp.gwt.client.util.panel.ODIE_ButtonItemPanel;

public class ODIE_SemanticTypePickerItem extends TextItem implements
		RecordClickHandler {

	private static final String KEY_LOCAL_SEMANTIC_TYPE_ID = "tui";

	private static final String KEY_SEMANTIC_TYPE_NAME = "semanticTypeName";
	
	private static final String CONST_HTML_BR = "<br>" ;
	
	private static final String CONST_EMPTY_HEADER = "&nbsp;" + CONST_HTML_BR;

	private static ODIE_SemanticTypePickerItem currentEditor;

	private static Dialog dialog;

	private static ListGrid semanticTypePickerGrid = null;

	private static Label accumulatorLabel = new Label();

	private static IButton deSelectAllIButton;
	private static IButton deSelectLastIButton;
	private static IButton selectCurrentIButton;
	private static IButton selectAllCurrentIButton;
	private static IButton useAllIButton;

	private static ButtonItem selectButtonItem;

	private static ButtonItem cancelButtonItem;

	private static void makeDialog() {
		dialog = new Dialog();
		dialog.setTitle("SemanticType Picker") ;
		dialog.setAutoCenter(true);
		dialog.setIsModal(false);
		dialog.setShowHeader(true);
		dialog.setShowEdges(true);
		dialog.setEdgeSize(10);
		dialog.setShowToolbar(false);
		dialog.setWidth(530);
		dialog.setHeight(285);

		semanticTypePickerGrid = buildSemanticTypePickerGrid();
		accumulatorLabel = buildLabel();

		HLayout pickerPanel = new HLayout();
		pickerPanel.setMembersMargin(5);
		pickerPanel.setLayoutMargin(5);
		pickerPanel.addMember(semanticTypePickerGrid);
		pickerPanel.addMember(buildDialogButtonPanel());
		pickerPanel.addMember(accumulatorLabel);
		pickerPanel.setHeight(200);

		// Map bodyDefaults = new HashMap();
		// bodyDefaults.put("layoutLeftMargin", 5);
		// bodyDefaults.put("membersMargin", 10);
		// dialog.setBodyDefaults(bodyDefaults);

		dialog.addItem(pickerPanel);
		dialog.addItem(buildActionsPanel());

	}

	private static LayoutSpacer buildLayoutSpacer() {
		LayoutSpacer result = new LayoutSpacer();
		result.setHeight(5);
		return result;
	}

	private static IButton buildIButton(String title) {
		IButton result = new IButton(title);
		result.setWidth(30);
		result.setTitleStyle("{font-style:bold; font-size:10px}");
		return result;
	}

	private static Label buildLabel() {
		Label result = new Label();
		result.setHeight100();
		result.setWidth("25%") ;
		result.setBorder("1px solid black");
		result.setValign(VerticalAlignment.TOP) ;
		result.setContents(CONST_EMPTY_HEADER) ;
		return result;
	}
	
	private static void updateAccumulatorContentsFromSelection(int upperBoundToAdd) {
		final Record[] selectedRecords = semanticTypePickerGrid
		.getSelection();
		String contents = accumulatorLabel.getContents() ;
		if (selectedRecords != null) {
			int entriesAdded = 0 ;
			for (int idx = 0; idx < selectedRecords.length; idx++) {
				Record firstSelectedRecord = selectedRecords[idx];
				String tui = firstSelectedRecord
				.getAttribute(KEY_LOCAL_SEMANTIC_TYPE_ID);
				if (contents.indexOf(tui + CONST_HTML_BR) == -1) {
					contents = unsetAll(contents) + tui + CONST_HTML_BR ;
					entriesAdded++ ;
					if (upperBoundToAdd > 0 && entriesAdded == upperBoundToAdd) {
						break ;
					}
				}
			}
		}
		accumulatorLabel.setContents(contents) ;
	}
	
	private static String unsetAll(String contents) {
		if (contents.endsWith("all" + CONST_HTML_BR)) {
			contents = CONST_EMPTY_HEADER ;
		}
		return contents ;
	}
	
	private static void setAll() {
		accumulatorLabel.setContents(CONST_EMPTY_HEADER + "all" + CONST_HTML_BR) ;
	}


	private static VStack buildDialogButtonPanel() {

		VStack layout = new VStack();
		layout.setWidth(40);
		layout.setLayoutMargin(5);
		layout.setMembersMargin(5);

		layout.addMember(buildLayoutSpacer());

		deSelectAllIButton = buildIButton("<<");
		deSelectAllIButton
				.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
					public void onClick(
							com.smartgwt.client.widgets.events.ClickEvent event) {
						accumulatorLabel.setContents(CONST_EMPTY_HEADER);

					}
				});
		layout.addMember(deSelectAllIButton);

		layout.addMember(buildLayoutSpacer());

		deSelectLastIButton = buildIButton("<");
		deSelectLastIButton
				.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
					public void onClick(
							com.smartgwt.client.widgets.events.ClickEvent event) {
						String contents = accumulatorLabel.getContents();
						contents = contents.replaceAll("[0-9a-zA-z]+<br>$", "") ;
						if (contents.length() == 0) {
							contents = CONST_EMPTY_HEADER ;
						}
						accumulatorLabel.setContents(contents);

					}
				});
		layout.addMember(deSelectLastIButton);

		layout.addMember(buildLayoutSpacer());

		selectCurrentIButton = buildIButton(">");
		selectCurrentIButton
				.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
					public void onClick(
							com.smartgwt.client.widgets.events.ClickEvent event) {
						int entriesUpperBound = 1 ;
						updateAccumulatorContentsFromSelection(entriesUpperBound) ;
					}
				});
		layout.addMember(selectCurrentIButton);

		layout.addMember(buildLayoutSpacer());

		selectAllCurrentIButton = buildIButton(">>");
		selectAllCurrentIButton
				.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
					public void onClick(
							com.smartgwt.client.widgets.events.ClickEvent event) {
						int entriesUpperBound = -1 ; // unbounded
						updateAccumulatorContentsFromSelection(entriesUpperBound) ;
					}
				});
		layout.addMember(selectAllCurrentIButton);

		layout.addMember(buildLayoutSpacer());

		useAllIButton = buildIButton("All");
		useAllIButton
				.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
					public void onClick(
							com.smartgwt.client.widgets.events.ClickEvent event) {
						setAll() ;
					}
				});
		layout.addMember(useAllIButton);

		layout.addMember(buildLayoutSpacer());

		return layout;
	}

	private static ListGrid buildSemanticTypePickerGrid() {

		final ListGrid semanticTypeGrid = ODIE_ClientUtils.buildListGrid();

		DataSource semanticTypeDS = buildSemanticTypeDataSource();

		semanticTypeGrid.setDataSource(semanticTypeDS);
		semanticTypeGrid.setSortField("semanticTypeName");
		semanticTypeGrid.addRecordClickHandler(currentEditor);
		semanticTypeGrid.setAutoFetchData(true);
		semanticTypeGrid.setCanEdit(false);
		semanticTypeGrid.setAlternateRecordStyles(true);
		semanticTypeGrid.setShowAllRecords(true);
		semanticTypeGrid.setAutoFetchData(true);
		semanticTypeGrid.setCanEdit(false);
		semanticTypeGrid.setSelectionType(SelectionStyle.SINGLE);
		semanticTypeGrid.setCanHover(false);
		semanticTypeGrid.setCanSelectAll(false);
		semanticTypeGrid.setShowHeader(false);
		semanticTypeGrid.setShowHover(false);

		semanticTypeGrid.setHeight100();
		semanticTypeGrid.setWidth("75%") ;

		return semanticTypeGrid;

	}

	private static void hideAndResetDialog() {
		accumulatorLabel.setContents(CONST_EMPTY_HEADER);
		semanticTypePickerGrid.deselectAllRecords();
		dialog.hide();
	}

	public static DynamicForm buildActionsPanel() {
		selectButtonItem = ODIE_ClientUtils.buildButtonItem("Select",
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						String newValue = accumulatorLabel.getContents().replaceAll(CONST_HTML_BR, ",") ;
						newValue = newValue.replaceAll("^&nbsp;,", "") ;
						newValue = newValue.replaceAll("[,]+$", "") ;
						currentEditor.setValue(newValue);
						hideAndResetDialog();
					}
				});
		cancelButtonItem = ODIE_ClientUtils.buildButtonItem("Cancel",
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						hideAndResetDialog();
					}
				});
		ArrayList<ButtonItem> buttons = new ArrayList<ButtonItem>();
		buttons.add(selectButtonItem);
		buttons.add(cancelButtonItem);
		return new ODIE_ButtonItemPanel("Actions", buttons);
	}

	private static DataSource buildSemanticTypeDataSource() {
		DataSource dataSource = new DataSource();
		dataSource.setShowPrompt(false) ;
		// <list>
		// <obs.common.beans.OntologyBean>
		// <localOntologyID>13305</localOntologyID>
		// <ontologyName>Common Anatomy Reference Ontology</ontologyName>
		// <ontologyVersion>1.3</ontologyVersion>
		// <virtualOntologyID>1063</virtualOntologyID>
		dataSource.setDataFormat(DSDataFormat.XML);
		dataSource.setRecordXPath("//semanticType");
		dataSource.setDataURL("/data/dataIntegration/xml/tuis.xml");
		DataSourceTextField tuiField = new DataSourceTextField(
				"tui", "tui");
		DataSourceTextField styField = new DataSourceTextField(
				"sty", "sty");
		dataSource.setFields(tuiField, styField);
		return dataSource;
	}

	public void onRecordClick(RecordClickEvent event) {
		; 
	};

	// show the picker dialog at the specified position
	private static void showDialog(int left, int top) {
		dialog.show();
		dialog.moveTo(left, top);
	}

	public ODIE_SemanticTypePickerItem() {

		addKeyPressHandler(new KeyPressHandler() {
			public void onKeyPress(KeyPressEvent event) {
				event.cancel();
			}
		});

		// use default trigger icon here. User can customize.
		// [SKIN]/DynamicForm/default_formItem_icon.gif
		FormItemIcon formItemIcon = new FormItemIcon();
		setIcons(formItemIcon);

		addIconClickHandler(new IconClickHandler() {
			public void onIconClick(IconClickEvent event) {

				// get global coordinates of the clicked picker icon
				Rectangle iconRect = getIconPageRect(event.getIcon());

				// remember what editor is active, so we can set its value from
				// the picker dialog
				ODIE_SemanticTypePickerItem.currentEditor = ODIE_SemanticTypePickerItem.this;

				// lazily create the YesNoMaybe picker dialog the first time a
				// yesNoMaybe editor is clicked
				if (ODIE_SemanticTypePickerItem.dialog == null) {
					ODIE_SemanticTypePickerItem.makeDialog();
				}

				// initialize the accumulatorLabel from the TextItem contents
				String textItemContents = (String) ODIE_SemanticTypePickerItem.currentEditor
						.getValue();
				textItemContents = (textItemContents == null || textItemContents.length() == 0) ? CONST_EMPTY_HEADER
						: CONST_EMPTY_HEADER + textItemContents.replaceAll(",", CONST_HTML_BR) + CONST_HTML_BR;

				ODIE_SemanticTypePickerItem.accumulatorLabel
						.setContents(textItemContents);

				// show the picker dialog
				ODIE_SemanticTypePickerItem.showDialog(iconRect.getLeft(), iconRect
						.getTop());
			}
		});
	}

}

